
package Math;

/* Start of 'ByteStock' class */
public class ByteStock
{
  private byte Bulk[];
  int Size, MaxSize, AllocSize;

  /* 'ByteStock' class constructor
   * ARGUMENTS:
   *   - data allocation size
   *       int AllocSize;
   * RETURNS: None.
   */
  public ByteStock( int AllocSize )
  {
    Size = MaxSize = 0;
    this.AllocSize = AllocSize;
  } /* End of 'ByteStock' class constructor */

  /* Add byte array function
   * ARGUMENTS:
   *   - reference to byte array
   *       byte Data[];
   *   - adding data size
   *       int Len;
   * RETURNS:
   *   - self reference
   *       ByteStock;
   */
  public ByteStock Add(byte Data[], int Len )
  {
    int NewAlloc;

    if (MaxSize - Size < Len)
    {
      if (Len > AllocSize)
        NewAlloc = Len;
      else
        NewAlloc = AllocSize;
      byte NewBulk[] = new byte[MaxSize + NewAlloc];
      if (Size != 0)
        System.arraycopy(Bulk, 0, NewBulk, 0, Size);
      Bulk = NewBulk;
      MaxSize += NewAlloc;
    }
    System.arraycopy(Data, 0, Bulk, Size, Len);
    Size += Len;

    return this;
  } /* End of 'Add' function */

  /* Delete bytes from start function
   * ARGUMENTS:
   *   - number of bytes to delete
   *       int Num;
   * RETURNS:
   *   - self reference
   *       ByteStock;
   */
  public ByteStock DeleteStart( int Num )
  {
    System.arraycopy(Bulk, Num, Bulk, 0, Num);
    Size -= Num;
    Realloc();

    return this;
  } /* End of 'DeleteStart' function */

  /* Delete bytes from end function
   * ARGUMENTS:
   *   - number of bytes to delete
   *       int Num;
   * RETURNS:
   *   - self reference
   *       ByteStock;
   */
  public ByteStock DeleteLast( int Num )
  {
    if (Size <= Num)
      Size = 0;
    else
      Size -= Num;
    Realloc();

    return this;
  } /* End of 'DeleteLast' function */

  /* Delete byte stock elements in interval
   * ARGUMENTS:
   *   - interval start and end
   *       int From, To;
   * RETURNS:
   *   - self reference
   *       Stock;
   */
  public ByteStock DeleteInterval( int From, int To )
  {
   if (From < 0)
      From = 0;
    if (To < 0)
      To = 0;
    if (To < From)
    {
      int Inc = To;
      To = From;
      From = Inc;
    }
    if (To >= Size - 1)
      Size = From;
    else
    {
      System.arraycopy(Bulk, To + 1, Bulk, From, Size - To - 1);
      Size -= To - From + 1;
    }

    Realloc();

    return this;
  } /* End of 'DeleteInterval' function */

  /* Get bytes function
   * ARGUMENTS:
   *   - number of bytes to get
   *       int Num;
   * RETURNS:
   *   - byte array reaaded
   *       byte Mas[];
   */
  public byte[] GetBytes( int Num )
  {
    if (Size == 0)
      return new byte[0];
    if (Num > Size)
      Num = Size;
    byte Buf[] = new byte[Num];
    System.arraycopy(Bulk, 0, Buf, 0, Num);
    for (int i = 0; i < Size - Num; i++)
      Bulk[i] = Bulk[Num + i];
    Size -= Num;
    return Buf;
  } /* End of 'GetBytes' function */

  /* Realloc byte stock`s memory function
   * ARGUMENTS: None.
   * RETURNS: None.
   */
  private void Realloc( )
  {
    if (MaxSize - Size > 2 * AllocSize)
    {
      byte NewBulk[] = new byte[Size + AllocSize];
      System.arraycopy(Bulk, 0, NewBulk, 0, Size);
      Bulk = NewBulk;
      MaxSize = Size + AllocSize;
    }
  } /* End of 'Realloc' function */

  /* Free stock of bytes function
   * ARGUMENTS: None.
   * RETURNS:
   *   - self reference
   *       ByteStock;
   */
  public ByteStock Free( )
  {
    Size = MaxSize = 0;
    Bulk = null;

    return this;
  } /* End of 'Free' function */

} /* End of 'ByteStock' class */
